package com.jdk.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ConsumerTest {
    public static void main(String[] args) {
       //ProDao pd = new ProducerImpl();//被代理类 ProducerImpl
        ProducerImpl pd = new ProducerImpl();//真实角色
        pd.sellProduct(20000f);
        System.out.println("------------");
        /**
         * jdk动态代理
         * 前提条件, 必须代理类实现一个接口
         *  提供者:jdk提供的
         *   public static Object newProxyInstance(
         *   ClassLoader loader,  类加载:随用随创建,边用边加载,加载被代理角色代理的字节码文件
         *   Class<?>[] interfaces, 字节码数组:和被代理角色提供相同的字节码文件
         *   InvocationHandler h就是对业务方法进行增强参数,代理的处理程序, 要么是接口子实现类,要么是匿名内部类
         *   )
         *
         */
        ProDao proDao = (ProDao) Proxy.newProxyInstance(
                ProducerImpl.class.getClassLoader(),
                ProducerImpl.class.getInterfaces(),
                new InvocationHandler() {
                    //业务方法被增强的代码
                    /**
                     * 被代理的角色的所有业务方法都需要经过这个方法
                     * @param proxy 代理对象的引用
                     * @param method 当前执行的方法
                     * @param args 当前执行方法的形参
                     * @return 和被代理的角色一致(获取代理角色)
                     * @throws Throwable
                     */
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args)
                            throws Throwable {
                        //声明Object对象
                        Object obj = null;
                        //反射:method.invoke(代理类的实例,方法中的实际参数)
                        //获取被代理类中业务方法的参数args
                        Float money = (Float) args[0];
                        if ("sellProduct".equals(method.getName())){
                            obj = method.invoke(pd, money*0.5f);
                        }
                        return obj;
                    }
                });
        //代理角色
        proDao.sellProduct(200f);
    }
}
